/*
 * dtrpulse.c
 * Pulses DTR on specified serial port for specified milliseconds
 * Copyright 2009 Eric E. Westbrook
 * License granted under GNU Public License v2.0
 * See http://
 * Follow up with avrdude -F -p m168 -P /dev/ttyUSB0 -c stk500v1 -b 19200 -t
 */

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <time.h>

int usage(char** argv) {
  printf("Usage: %s device [milliseconds]\n", argv[0]);
  return 1;
}

void sleep_ms(long ms) {
  struct timespec ts;
  ts.tv_sec = ms / 1000;
  ts.tv_nsec = ms % 1000 * 1000000;
  nanosleep(&ts, NULL);  
}

int open_port(char* portname) {
  int fd;
  fd = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
  if (-1 == fd) {
    char msg[128];
    snprintf(msg, 128, "dtrpulse: open_port(\"%s\") fails", portname);
    perror(msg);
  } else {
    fcntl(fd, F_SETFL, 0);
  }
  return (fd);
}

void pulse_dtr(fd) {
  struct termios options;
  tcgetattr(fd, &options);
  options.c_cflag |= (CLOCAL | CREAD);

  cfsetispeed(&options, B19200);
  tcsetattr(fd, TCSANOW, &options);
  sleep_ms(100);

  cfsetospeed(&options, B0);
  tcsetattr(fd, TCSANOW, &options);
  sleep_ms(100);
}

int main(int argc, char** argv) {
  if (2 != argc && 3 != argc) { return usage(argv); }

  long pulse_ms = (2 == argc ? 100 : atol(argv[2]));
  if (!pulse_ms) { return usage(argv); }

  printf("Pulsing DTR on %s for %d ms\n", argv[1], pulse_ms);

  int fd = open_port(argv[1]);
  pulse_dtr(fd, pulse_ms);
  return 0;
}
